/**
 * This file is Copyright © 2008 Software Craftsmen Limited. All Rights Reserved.
 */
package com.softwarecraftsmen.archivers.zip.zipEntryAndData;

import com.softwarecraftsmen.orogeny.filing.AbsoluteFile;
import com.softwarecraftsmen.orogeny.filing.RelativeFile;
import static com.softwarecraftsmen.orogeny.filing.fileSystems.ZipFileSystem.ZipFileSystemRoot;
import com.softwarecraftsmen.inputStreamReaders.CopyingInputStreamReader;
import com.softwarecraftsmen.inputStreamReaders.InputStreamReader;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.io.IOException;
import static java.lang.String.format;
import static java.util.Locale.UK;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

public class AbsoluteFileBackedZipEntryAndData implements ZipEntryAndData
{
	private final AbsoluteFile fileOnDisk;
	private final ZipEntry zipEntry;

	public AbsoluteFileBackedZipEntryAndData(final @NotNull AbsoluteFile fileOnDisk, final @NotNull RelativeFile fileInZip)
	{
		this.fileOnDisk = fileOnDisk;
		zipEntry = new ConvenientZipEntry(fileInZip.toFileSystemSpecificPath(ZipFileSystemRoot), fileOnDisk.dynamicMetaData().modificationTimeInMillisecondsSince1970());
	}

	@NotNull
	public String toString()
	{
		return format(UK, "%1$s(%2$s, %3$s)", getClass().getSimpleName(), fileOnDisk, zipEntry);
	}

	public boolean equals(final @Nullable Object o)
	{
		if (this == o)
		{
			return true;
		}
		if (o == null || getClass() != o.getClass())
		{
			return false;
		}

		final AbsoluteFileBackedZipEntryAndData that = (AbsoluteFileBackedZipEntryAndData) o;
		return fileOnDisk.equals(that.fileOnDisk) && zipEntry.equals(that.zipEntry);
	}

	public int hashCode()
	{
		int result;
		result = fileOnDisk.hashCode();
		result = 31 * result + zipEntry.hashCode();
		return result;
	}

	public void write(final @NotNull ZipOutputStream outputStream) throws IOException
	{
		outputStream.putNextEntry(zipEntry);
		fileOnDisk.readData(new CopyingInputStreamReader(outputStream));
		outputStream.closeEntry();
	}

	@NotNull
	public String pathNameInsideZip()
	{
		return zipEntry.getName();
	}

	@NotNull
	public <T> T readData(final @NotNull InputStreamReader<T> inputStreamReader) throws IOException
	{
		return fileOnDisk.readData(inputStreamReader);
	}
}
